package com.zhoumy.juc.cas;


/**
 * 题目：实现一个自旋锁，借鉴CAS思想
 * 自旋锁好处，循环比较获取没有类似wait阻塞
 * 通过CAS完成自旋锁，A线程先进来调用myLock方法自己持有锁5秒钟，B随后进来后发现
 * 当前有线程持有锁，所以只能通过自旋等待，直到A释放锁后B随后抢到。
 */

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author zhoumy
 * @create 2024年6月17日20:48:33
 */
public class SpinLockDemo {


    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    /**
     * 加锁
     */
    public void lock() {
        Thread thread = Thread.currentThread();

        /**
         * 第一个线程进来肯定希望没有线程，这样自己就可以填充
         * 所有参数是 null thread(自己)
         */

        /**
         * 这里取反：
         * 假设A线程进来，发现是null,那么将自身（A线程）写入成功，返回true,取反 返回false
         * 跳出循环
         */
        System.out.println(Thread.currentThread().getName() + "\t" + "------come in");
        while (!atomicReference.compareAndSet(null, thread)) {

        }
        ;

    }

    /**
     * 解锁
     */
    public void unLock() {
        /**
         * 获取当前线程
         */
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread, null);
        System.out.println(Thread.currentThread().getName() + "\t" + "------task over，unLock...");
    }

    public static void main(String[] args) {
        SpinLockDemo spinLockDemo = new SpinLockDemo();
        new Thread(() -> {
            spinLockDemo.lock();
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.unLock();
        }, "A").start();


        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            spinLockDemo.lock();
            spinLockDemo.unLock();
        }, "B").start();
    }
}
